#pragma once
#include<iostream>
#include<sys/epoll.h>
#include<stdlib.h>

#include"Log.hpp"
#include"Comm.hpp"

static const int gsize=128;
class Multiplex//select poll  epoll父类
{
public:
    virtual bool AddEvent(int fd,uint32_t events)=0;
    virtual bool ModEvent(int fd,uint32_t events)=0;//修改
    virtual bool DelEvent(int fd)=0;
    virtual int Wait(struct epoll_event revs[],int num,int timeout)=0;//若是需要做select和poll从新设计接口参数
};
class Epoller : public Multiplex
{
private:
    bool ModEventHelper(int fd,uint32_t events,int oper)
    {
        struct epoll_event ev;
        ev.events=events;
        ev.data.fd=fd;
        int n=::epoll_ctl(_epfd,oper,fd,&ev);
        if(n<0)
        {
            LOG(ERROR,"epoll_ctr  %d events %s failed\n",fd,EventToString(events).c_str());
            return false;
        }
        LOG(INFO,"epoll_ctr  %d events %s success\n",fd,EventToString(events).c_str());
        return true;
    }
    
public:
    Epoller()
    {
        _epfd=::epoll_create(gsize);
        if(_epfd<0)
        {
            LOG(FATAL,"epoll error\n");
            exit(EPOLL_CREATE_ERROR);
        }
        LOG(INFO,"epoll create success epfd:%d\n",_epfd);
    }
    std::string EventToString(uint32_t events)
    {
        std::string eventstr;
        if(events & EPOLLIN)eventstr="EPOLLIN";
        if(events & EPOLLOUT)eventstr+="|EPOLLOUT";
        if(events & EPOLLET)eventstr+="|EPOLLET";
        return eventstr;
    }
    bool AddEvent(int fd,uint32_t events) override
    {
        return ModEventHelper(fd,events,EPOLL_CTL_ADD);
    }
    bool ModEvent(int fd,uint32_t events) override
    {
        return ModEventHelper(fd,events,EPOLL_CTL_MOD);
    }
    bool DelEvent(int fd) override
    {
        return 0==::epoll_ctl(_epfd,EPOLL_CTL_DEL,fd,nullptr);
    }

    int Wait(struct epoll_event revs[],int num,int timeout) override//若是做成虚函数需要从新设计接口参数
    {
        return ::epoll_wait(_epfd,revs,num,timeout);
    }
    ~Epoller(){}
private:
    int _epfd;
};